package com.olap.starter.common.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.DbType;
import com.olap.starter.common.util.OnlineUtils;
import com.olap.starter.common.util.QueryGeneratorUtil;
import com.olap.starter.common.util.SqlUtils;
import com.olap.starter.common.util.TaleSqlUtil;
import com.olap.starter.common.vo.ExecuteQuery;
import com.olap.starter.common.vo.QueryData;
import com.olap.starter.common.vo.QueryParameter;
import com.olap.starter.config.dataSource.JdbcTemplateSource;
import com.olap.starter.core.response.Result;
import com.olap.starter.core.response.ResultUtil;
import com.olap.starter.util.StringUtils;
import com.olap.starter.pojo.TableDelete;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.olap.starter.common.util.TaleSqlUtil.getTableName;

/**
 * @author WBG
 * @date 2024/2/2 11:22
 * @describe
 */
@Service
@Slf4j
@AllArgsConstructor
public class CRUDServices {
    private final JdbcTemplateSource jdbcTemplateSource;
    private static final ExecutorService executor = Executors.newFixedThreadPool(5);

    public QueryData doGetData(QueryParameter queryParameter) {
        long start = System.currentTimeMillis();
        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(queryParameter.getDbName());
        queryParameter.setDbType(SqlUtils.getDbType(jdbcTemplate));
        ExecuteQuery executeQuery = QueryGeneratorUtil.initQuery(queryParameter);
        QueryData queryData = doCall(jdbcTemplate, executeQuery);
        long end = System.currentTimeMillis();
        log.info("==>  执行sql耗时：" + (end - start) + "");
        return queryData;
    }

    private QueryData doCall(JdbcTemplate jdbcTemplate, ExecuteQuery executeQuery) {
        String exSql = QueryGeneratorUtil.replacePlaceholdersWithQuestionMarks(executeQuery.getExSql());
        String exSqlc = QueryGeneratorUtil.replacePlaceholdersWithQuestionMarks(executeQuery.getExCountSql());
        Object[] sqlAndParams = QueryGeneratorUtil.getSqlAndParams(executeQuery);

        log.info("==>  listSQL:\n" + executeQuery.getExSqlStr());
        //log.info("==>  countSQL:\n" + exSqlc);
        CompletableFuture<List<Map<String, Object>>> list = CompletableFuture.supplyAsync(() -> jdbcTemplate.queryForList(exSql, sqlAndParams), executor);
        CompletableFuture<Map<String, Object>> map = CompletableFuture.supplyAsync(() -> jdbcTemplate.queryForMap(exSqlc, sqlAndParams), executor);
        CompletableFuture.allOf(list, map).join();
        try {
            return new QueryData(list.get(), map.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    public List<Map<String, Object>> doGetDataList(String exSql, String dbName) {
        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(dbName);
        if (StringUtils.isBlank(exSql)) {
            exSql = TaleSqlUtil.getTablesSql(jdbcTemplate);
        }
        log.info("执行SQL：" + exSql);
        return doGetDataList(exSql, jdbcTemplate);
    }

    public List<Map<String, Object>> doGetDataList(String exSql, JdbcTemplate jdbcTemplate) {
        log.info("执行SQL：" + exSql);
        return jdbcTemplate.queryForList(exSql);
    }

    public List<Map<String, Object>> doGetDataList(String exSql, String dbName, String tableName) {
        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(dbName);
        exSql = TaleSqlUtil.getColumnsSql(getTableName(jdbcTemplate), tableName, jdbcTemplate);
        return doGetDataList(exSql, jdbcTemplate);
    }

    public List<Map<String, Object>> doGetDataList(String exSql, String dbName, Object[] obj) {
        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(dbName);
        return jdbcTemplate.queryForList(exSql, obj);
    }

    public Result delete(Map<String, Object> map) {
        if(map.get("$parentId") == null){
            return ResultUtil.error("非法操作！");
        }
        String sql = " SELECT A.*,C.DB_NAME\n" +
                "        FROM TABLE_DELETE A\n" +
                "                 JOIN TABLE_CONFIG B ON A.PARENT_ID = B.ID\n" +
                "                 JOIN TABLE_MAIN C ON C.UUID = B.UUID AND C.DELETED = 0\n" +
                "        WHERE B.ID = ?";
        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(null);
        TableDelete tableDelete = jdbcTemplate.queryForObject(sql, new Object[]{map.get("$parentId")},TableDelete.class);
        //TableDelete tableDelete = tableDeleteServices.getBaseMapper().getTableDeleteAndDbName(Long.valueOf(map.get("$parentId").toString()));
        if (tableDelete == null) {
            return ResultUtil.error("无效的$parentId！");
        }
        return doDelete(map, tableDelete);
    }

    public Result doDelete(Map<String, Object> map, TableDelete tableDelete) {
        Map<String, Object> filedMap = OnlineUtils.parseWhereToMap(tableDelete, true);
        Object[] objects = new Object[filedMap.size()];
        int index = 0;
        for (String k : filedMap.keySet()) {
            String fk = OnlineUtils.getFontFiled(filedMap.get(k).toString());
            Object o = map.get(fk);
            if (o == null) {
                return ResultUtil.error("删除条件[\"+fk+\"]不能为空！");
            }
            objects[index] = map.get(fk);
            index++;
        }

        JdbcTemplate jdbcTemplate = jdbcTemplateSource.getJdbcTemplate(tableDelete.getDbName());
        String deleteSql = OnlineUtils.getDeleteSql(tableDelete, filedMap, isDelete(jdbcTemplate, tableDelete.getTableName()));
        log.info("==>  Preparing:\n" + deleteSql);
        log.info("==> Parameters:\n" + JSON.toJSONString(objects));
        int i = jdbcTemplate.update(deleteSql, objects);
        log.info("\n<==      Total: " + i);
        if (i == 0) {
            return ResultUtil.error("删除失败！");
        }
        return ResultUtil.success("删除成功！");
    }

    private boolean isDelete(JdbcTemplate jdbcTemplate, String tableName) {
        if (DbType.MYSQL.equals(SqlUtils.getDbType(jdbcTemplate))) {
            String sql = "SELECT COUNT(*) as cunt FROM information_schema.columns WHERE table_schema = 'online' AND table_name = '" + tableName + "' AND column_name = 'deleted'";
            Map<String, Object> map1 = jdbcTemplate.queryForMap(sql);
            return Integer.parseInt(map1.get("cunt").toString()) == 0;
        }
        return true;
    }

}
